package cloud.tianai.mate.captcha.generator.impl;

import scala.reflect.internal.Trees;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.*;
import java.awt.image.BufferedImage;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.ThreadLocalRandom;

public class Demo {


    public static void main(String[] args) throws IOException {
        BufferedImage bufferedImage = new BufferedImage(600, 360, BufferedImage.TYPE_INT_RGB);
        // 设置图片背景色为白色
        bufferedImage.setRGB(0, 0, 0xffffff);
        Graphics2D g = bufferedImage.createGraphics();
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, 600, 360);

        ThreadLocalRandom random = ThreadLocalRandom.current();
        Color color1 = new Color(random.nextInt(255),
                random.nextInt(255),
                random.nextInt(255),
                random.nextInt(100,150));
        Color color2 = new Color(random.nextInt(255),
                random.nextInt(255),
                random.nextInt(255),
                random.nextInt(100,150));

        Point2D.Double start = new Point2D.Double(0, 0);
        Point2D.Double end = new Point2D.Double(80, 80);
        g.setPaint(new GradientPaint(start, color1, end, color2));
        g.setStroke( new ShapeStroke(new Shape[] {
                new Ellipse2D.Float(0, 0, 10, 10)
        },
                15.0f));
//        g.drawLine(10, 10, 80, 80);

        Path2D path = new Path2D.Double();
        // 开始构建路径，从起点开始
        path.moveTo(10, 10);
        // 添加三次贝塞尔曲线段
        path.curveTo(10, 10, 500, 300, 600, 10);
        g.draw(path);
        g.dispose();
        FileOutputStream fileOutputStream = new FileOutputStream("C:\\Users\\Thinkpad\\Desktop\\captcha\\temp\\新建文件夹\\xx.jpg");
        ImageIO.write(bufferedImage, "jpg", fileOutputStream);
        fileOutputStream.close();

    }

    public static class ShapeStroke implements Stroke {
        private Shape shapes[];
        private float advance;
        private boolean stretchToFit = false;
        private boolean repeat = true;
        private AffineTransform t = new AffineTransform();
        private static final float FLATNESS = 1;

        public ShapeStroke( Shape shapes, float advance ) {
            this( new Shape[] { shapes }, advance );
        }

        public ShapeStroke( Shape shapes[], float advance ) {
            this.advance = advance;
            this.shapes = new Shape[shapes.length];

            for ( int i = 0; i < this.shapes.length; i++ ) {
                Rectangle2D bounds = shapes[i].getBounds2D();
                t.setToTranslation( -bounds.getCenterX(), -bounds.getCenterY() );
                this.shapes[i] = t.createTransformedShape( shapes[i] );
            }
        }

        public Shape createStrokedShape( Shape shape ) {
            GeneralPath result = new GeneralPath();
            PathIterator it = new FlatteningPathIterator( shape.getPathIterator( null ), FLATNESS );
            float points[] = new float[6];
            float moveX = 0, moveY = 0;
            float lastX = 0, lastY = 0;
            float thisX = 0, thisY = 0;
            int type = 0;
            boolean first = false;
            float next = 0;
            int currentShape = 0;
            int length = shapes.length;

            float factor = 1;

            while ( currentShape < length && !it.isDone() ) {
                type = it.currentSegment( points );
                switch( type ){
                    case PathIterator.SEG_MOVETO:
                        moveX = lastX = points[0];
                        moveY = lastY = points[1];
                        result.moveTo( moveX, moveY );
                        first = true;
                        next = 0;
                        break;

                    case PathIterator.SEG_CLOSE:
                        points[0] = moveX;
                        points[1] = moveY;
                        // Fall into....

                    case PathIterator.SEG_LINETO:
                        thisX = points[0];
                        thisY = points[1];
                        float dx = thisX-lastX;
                        float dy = thisY-lastY;
                        float distance = (float)Math.sqrt( dx*dx + dy*dy );
                        if ( distance >= next ) {
                            float r = 1.0f/distance;
                            float angle = (float)Math.atan2( dy, dx );
                            while ( currentShape < length && distance >= next ) {
                                float x = lastX + next*dx*r;
                                float y = lastY + next*dy*r;
                                t.setToTranslation( x, y );
                                t.rotate( angle );
                                result.append( t.createTransformedShape( shapes[currentShape] ), false );
                                next += advance;
                                currentShape++;
                                if ( repeat )
                                    currentShape %= length;
                            }
                        }
                        next -= distance;
                        first = false;
                        lastX = thisX;
                        lastY = thisY;
                        break;
                }
                it.next();
            }

            return result;
        }

    }

    public static class CompoundStroke implements Stroke {
        public final static int ADD = 0;
        public final static int SUBTRACT = 1;
        public final static int INTERSECT = 2;
        public final static int DIFFERENCE = 3;

        private Stroke stroke1, stroke2;
        private int operation;

        public CompoundStroke( Stroke stroke1, Stroke stroke2, int operation ) {
            this.stroke1 = stroke1;
            this.stroke2 = stroke2;
            this.operation = operation;
        }

        public Shape createStrokedShape( Shape shape ) {
            Area area1 = new Area( stroke1.createStrokedShape( shape ) );
            Area area2 = new Area( stroke2.createStrokedShape( shape ) );
            switch ( operation ) {
                case ADD:
                    area1.add( area2 );
                    break;
                case SUBTRACT:
                    area1.subtract( area2 );
                    break;
                case INTERSECT:
                    area1.intersect( area2 );
                    break;
                case DIFFERENCE:
                    area1.exclusiveOr( area2 );
                    break;
            }
            return area1;
        }
    }
}
